#include <REGX52.H>
#include "Delay_Utils.h"

//U1, 段选端
sbit NIXIE_DULA = P2^6;
//U2, 位选端
sbit NIXIE_WELA = P2^7;

//共阴极的数字:                            0~9
static code unsigned char Nixie_nums[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,
                                         //A   b     C     d     E     F
                                         0x77, 0x7C, 0X39, 0X5E, 0X79, 0X71,
                                         //无显示
                                         0x00};

/**
 * 点亮数码管, 注意:
 *      如果是扫描点亮多个数码管, 需要自己 Delayms(2~3); //需要延时(否则显示会比较暗)
 *                              或者自己使用 Timer 定时器, 每2~3ms扫描1次
 * 
 * @param isTx1C 是不是 TX-1C 开发板
 * @param position 点亮第几个数码管(从低位右开始)(1~8)
 * @param hex 显示的数码管 a~h 的 16进制
 * @param isClear 如果只点亮1个数码管, 传0.   如果扫描点亮多个数码管, 需要消影, 传1
 */
void Nixie_Tube_Light(bit isTx1C, unsigned char position, unsigned char hex, bit isClear) {
    //消影, 如果不清0, 数据会串到下一位去
    if (isClear) P0 = 0x00;
    //如果是 TX-1C
    if (isTx1C) {
        NIXIE_WELA = 1;   //打开位选锁存器(74HC573)的锁存端(TX-1C的数码管是由2个锁存器(74HC573) U1,U2 连接的)
        P0 = ~(1 << (position - 1));
        NIXIE_WELA = 0;   //关闭位选
        NIXIE_DULA = 1;   //打开段选
    } else {
        /**
         * 例: 让 LED6(四位一体数码管)亮,
         * LED6对应 138译码器(74LS138)的Y5口, 对应的输入二进制=101
         * P2_2低位, P2_4高位
         */
        /**
         * 0: 000   1: 001  2: 010  3: 011
         * 4: 100   5: 101  6: 110  7: 111
         */
        P2_4 = position >= 4;
        P2_3 = position == 2 || position == 3 || position == 6 || position == 7;
        P2_2 = position == 1 || position == 3 || position == 5 || position == 7;
    }
    
    //显示6: AFEDCG=1,   B&.DP=0  ==>  P0=0b0111 1101=0x7D
    P0 = hex;
    
    //如果是 TX-1C
    if (isTx1C) NIXIE_DULA = 0;
}

/**
 * 点亮数码管, 注意:
 *      如果是扫描点亮多个数码管, 需要自己 Delayms(2~3); //需要延时(否则显示会比较暗)
 *                              或者自己使用 Timer 定时器, 每2~3ms扫描1次
 * 
 * @param isTx1C 是不是 TX-1C 开发板
 * @param position 点亮第几个数码管(从低位右开始)(1~8)
 * @param num 显示的数字(0~9)
 * @param showPoint 是否显示右下角的"点"(0x80)    bit不能左移, ∴使用unsigned char
 * @param isClear 如果只点亮1个数码管, 传0.   如果扫描点亮多个数码管, 需要消影, 传1
 */
void Nixie_Tube_Light_Num(bit isTx1C, unsigned char position, unsigned char num, unsigned char showPoint, bit isClear) {
    Nixie_Tube_Light(isTx1C, position, Nixie_nums[num] | (showPoint << 7), isClear);
}

/**
 * 显示ERR
 */
void Nixie_Tube_Light_Error(bit isTx1C) {
    while (1) {
        Nixie_Tube_Light(isTx1C, 1, Nixie_nums[14], 1);
        Delayms(1);
        Nixie_Tube_Light(isTx1C, 2, Nixie_nums[10], 1);
        Delayms(1);
        Nixie_Tube_Light(isTx1C, 3, Nixie_nums[10], 1);
        Delayms(1);
    }
}
